---
title: Manage Secrets
sidebarTitle: "Manage Secrets"
description: "Securely handle API keys and user-provided credentials for cloud deployments"
icon: key
---

Secrets management in `mcp-agent cloud` has two phases:

1. **Deployment secrets** – values known at deploy time (provider API keys, service accounts, webhooks). Stored encrypted, mounted into the runtime automatically.
2. **User secrets** – values each consumer must supply (personal access tokens, OAuth refresh tokens). Collected per user via `mcp-agent cloud configure` and scoped to that user’s configuration.

Understanding the difference lets you ship reusable agents without exposing credentials.

## Secret files at a glance

| File | When | Contains | Checked into git? |
| --- | --- | --- | --- |
| `mcp_agent.secrets.yaml` | Before deploy | Raw values you author locally | **No** (add to `.gitignore`) |
| `mcp_agent.deployed.secrets.yaml` | Generated by `mcp-agent deploy` | Handles for deployment secrets, `!user_secret` placeholders | Yes – safe to commit |
| `mcp_agent.configured.secrets.yaml` | Generated by `mcp-agent cloud configure` | User-supplied secrets bound to secret handles | Optional – safe to share with that user only |
| `mcp_agent.deployed.config.yaml` | Generated by `mcp-agent deploy` | Materialized app settings consumed by the control plane | Yes – safe to commit |
| `.env.mcp-cloud` | Generated by `mcp-agent cloud env pull` | Dotenv-formatted environment secrets for local development | **No** (treat like `.env`) |

## Step 1 – author your secrets file

Create `mcp_agent.secrets.yaml` next to `mcp_agent.config.yaml`:

```yaml
openai:
  api_key: "sk-..."                 # deployment secret

notion:
  api_key: "!user_secret NOTION_KEY"  # user secret (collected later)

crm:
  base_url: "https://api.example.com"  # not a secret, but you can store config values too
```

You can tag secrets as user secrets in two ways:

```yaml
notion:
  api_key: "!user_secret NOTION_KEY"     # inline tagged value
```

or

```yaml
notion:
  api_key:
    !user_secret NOTION_KEY
```

Everything else is treated as a deployment secret by default.

### Capture environment variables during deploy

If you prefer to read sensitive values from your shell (or a CI secret store) instead of writing them into `mcp_agent.secrets.yaml`, declare them in the root `env` list inside `mcp_agent.config.yaml`:

```yaml mcp_agent.config.yaml
env:
  - OPENAI_API_KEY                      # look up from os.environ during deploy
  - {SUPABASE_URL: "https://db.example.com"}  # fallback literal if the env var is unset
```

Each entry can be either a plain string (read from `os.environ[KEY]`) or a single-key mapping that supplies a fallback value when the environment variable is missing. During `mcp-agent deploy` the CLI:

1. Resolves the value (environment first, then fallback).
2. Stores it as a deployment secret named `apps/<app_id>/env/<KEY>`.
3. Inserts the resulting handle into the `env:` list inside `mcp_agent.deployed.secrets.yaml`.

The runtime still references the value via `os.environ[KEY]`; the cloud control plane materialises the secret before your app starts.

## Step 2 – transform during deployment

When you run `mcp-agent deploy`, the CLI:

1. Loads `mcp_agent.secrets.yaml`.
2. Asks how to treat each value (unless already tagged or using `--non-interactive`).
3. Creates secrets via the cloud API and stores the resulting handles.
4. Writes `mcp_agent.deployed.secrets.yaml` and bundles it with your deployment.

Example output:

```
? Store OPENAI_API_KEY as a deployment secret?  [Y/n] y
? Tag NOTION_KEY as user secret?  [Y/n] y
✓ Created 1 deployment secret, 1 user secret placeholder
✓ Wrote mcp_agent.deployed.secrets.yaml (commit safe)
```

Generated file:

```yaml mcp_agent.deployed.secrets.yaml
openai:
  api_key: !secret mcpac_sc_5c0e2d7b-5b1b-41af-b5c7-91e0a7c5c6f5

notion:
  api_key: !user_secret NOTION_KEY
```

> Each `!secret` handle references an encrypted value stored in the control plane. Handles are opaque and cannot be used outside the deployment.

## Step 3 – collect end-user secrets (optional)

If you exposed any `!user_secret` entries, share the deployment URL with your users and have them run:

```bash
mcp-agent cloud configure \
  --id https://<app_id>.deployments.mcp-agent.com
```

`<app_id>` is the hostname printed in your deployment output (for example, `app_abc123xyz`).

The CLI:

1. Checks what user secrets are required (`--params` shows them without storing).
2. Prompts for each secret (or reads them from `--secrets-file`).
3. Writes `mcp_agent.configured.secrets.yaml` (unless `--dry-run`).
4. Uploads encrypted user secret handles tied to the caller’s API key.

Example output:

```
? Provide value for NOTION_KEY: ************************
✓ Stored 1 user secret
✓ Wrote mcp_agent.configured.secrets.yaml
```

Subsequent runs reuse stored values; use `--dry-run` to validate without persisting changes.

### Manage environment secrets after deployment

Use the `cloud env` commands to inspect or rotate values captured via the `env` list:

```bash
uvx mcp-agent cloud env list my-app
uvx mcp-agent cloud env add SUPABASE_URL https://db.example.com my-app
uvx mcp-agent cloud env remove SUPABASE_URL my-app
uvx mcp-agent cloud env add --from-env-file .env.local --app my-app
uvx mcp-agent cloud env pull my-app --format env
```

- `list` masks secret handles so you can confirm which keys are present.
- `add` updates the stored value (under the hood it calls the Secrets API and rewrites the handle if needed). Pass `--from-env-file <path>` to bulk import a dotenv-style file (comments and blank lines are ignored).
- `remove` deletes the value entirely.
- `pull` resolves values to either a dotenv file (default `.env.mcp-cloud`, matching Vercel’s `env pull`) or a YAML file, depending on `--format env|yaml`. The CLI auto-loads `.env` followed by `.env.mcp-cloud`, so pulled secrets are immediately available to your local commands while still respecting any developer-provided `.env` overrides.

All commands accept `--config-dir`, `--api-url`, and `--api-key` so they can read project defaults or run inside CI. Treat `.env.mcp-cloud` like any other `.env` file—add it to `.gitignore` and never commit it.

### Sharing with automated clients

- Provide `mcp_agent.configured.secrets.yaml` alongside the deployment URL for headless environments (CI, scheduled jobs).
- Re-run `mcp-agent cloud configure --params` in pipelines to assert the contract matches expectations.
- If you must rotate secrets automatically, script the configure command with `--secrets-file`.

## Accessing secrets in code

Secrets are injected into your app via the config layer. Use `app.config` or the global settings helper:

```python
from mcp_agent.config import get_settings

settings = get_settings()
openai_key = settings.openai.api_key           # decrypted value
notion_key = settings.notion.api_key           # user secret (per user)
```

You can also access them through environment variables if you prefer:

```python
import os
api_key = os.environ["OPENAI__API_KEY"]
```

> Deployment secrets are available to all users of the app. User secrets are scoped to the specific user/configuration that ran `mcp-agent cloud configure` and are only injected when that user’s API key is used to connect.

## Non-interactive + CI/CD

- **Reuse existing handles**: `mcp-agent deploy --non-interactive` reuses secrets stored in `mcp_agent.deployed.secrets.yaml` and fails if new values are required.
- **Custom API URL/keys**: set `MCP_API_KEY` (or use `--api-key`) and `MCP_API_BASE_URL` for staging environments.
- **Partial updates**: if you add a new entry to `mcp_agent.secrets.yaml`, the CLI prompts only for the new value.

## Advanced tips

<AccordionGroup>
  <Accordion title="MCP_APP_SETTINGS_PRELOAD">
    For local testing or one-off overrides, set `MCP_APP_SETTINGS_PRELOAD` to a YAML string that merges into the app settings before initialization. Useful when you do not want to create a secrets file on disk.
  </Accordion>
  <Accordion title="Secret reuse across deployments">
    Handles are per deployment. If you want to share the same credential across multiple apps, store the raw value in a secure password manager and paste it during each deploy. Secret rotation APIs are on the roadmap.
  </Accordion>
  <Accordion title="Auditing & rotation">
    Today rotation is manual (`mcp-agent deploy` with a new value). We log all secret creation/update events for future audit surfaces. Automatic rotation hooks are planned post-beta.
  </Accordion>
  <Accordion title="Workspace-scoped secrets">
    By default secrets are scoped to your user account. Team-wide sharing is coming with the upcoming workspace model—expect CLI flags to target a workspace instead of a personal scope.
  </Accordion>
</AccordionGroup>

## Troubleshooting

- **“Must have API key to process secrets”** – run `mcp-agent login` (or set `MCP_API_KEY`) before deploying.
- **Secrets not injected at runtime** – double-check `mcp_agent.deployed.secrets.yaml` is present in your project and that you are reading via `get_settings()`. Also ensure the file is not ignored by `.mcpacignore`.
- **Configure prompts unexpectedly** – you likely tagged a value as `!user_secret`. If it should be global, re-run `mcp-agent deploy` and choose “store as deployment secret”.
- **Need to revoke a user’s secrets** – run `mcp-agent cloud app revoke-config --id <configuration_id>` (coming soon). For now, delete the configuration via the API or ask the user to run configure again.

## Related docs

- [Deployment quickstart →](/cloud/deployment-quickstart)
- [Authentication options →](/cloud/authentication/deployment-auth)
- [Reference configuration schema →](/reference/configuration)
